<template>
  <div class="upload-container">
    <h2>文件上传</h2>
    
    <!-- 点击区域触发文件选择 -->
    <div 
      class="file-area"
      @click="chooseFile()"
      :class="{ 'file-area-active': isDragging }"
      @dragover.prevent="isDragging = true"
      @dragleave="isDragging = false"
      @drop.prevent="handleDrop"
    >
      <div class="upload-icon">
        <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
          <polyline points="17 8 12 3 7 8"></polyline>
          <line x1="12" y1="3" x2="12" y2="15"></line>
        </svg>
      </div>
      <p class="upload-text">
        点击或拖拽文件到此处(图片和视频可预览)
      </p>
      <p class="file-size-hint">最大支持 10MB</p>
    </div>

    <!-- 文件预览区域 -->
    <div class="preview-container" v-if="previewSrc">
      <div class="preview-header">
        <span class="preview-title">预览</span>
        <button class="remove-preview" @click="clearPreview">
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <line x1="18" y1="6" x2="6" y2="18"></line>
            <line x1="6" y1="6" x2="18" y2="18"></line>
          </svg>
        </button>
      </div>
      
      <img 
        v-if="fileType === 'image'" 
        :src="previewSrc" 
        class="preview-image"
        :alt="fileName"
        @load="previewLoaded"
      >
      <video 
        v-if="fileType === 'video'"
        :src="previewSrc" 
        class="preview-video" 
        controls
        @loadedmetadata="previewLoaded"
      ></video>
      <div v-if="fileType === 'other'" class="other-file-preview">
        <div class="file-icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path>
            <polyline points="14 2 14 8 20 8"></polyline>
            <line x1="16" y1="13" x2="8" y2="13"></line>
            <line x1="16" y1="17" x2="8" y2="17"></line>
            <polyline points="10 9 9 9 8 9"></polyline>
          </svg>
        </div>
        <div class="other-file-info">
          <div class="other-file-name">{{ fileName }}</div>
          <div class="other-file-size">{{ formatFileSize(fileSize) }}</div>
        </div>
      </div>
    </div>

    <!-- 显示文件名和大小 -->
    <div class="file-info" v-if="fileName && fileType === 'other'">
      <div class="file-name">{{ fileName }}</div>
      <div class="file-size">{{ formatFileSize(fileSize) }}</div>
    </div>

    <!-- 操作按钮区域 -->
    <div class="button-group" v-if="selectedFile">
      <button 
        class="upload-btn" 
        :disabled="isUploading || uploadProgress > 0 && uploadProgress < 100"
        @click="uploadFile"
      >
        <template v-if="!isUploading && uploadProgress === 0">上传文件</template>
        <template v-if="isUploading || (uploadProgress > 0 && uploadProgress < 100)">上传中...</template>
        <template v-if="uploadProgress === 100">上传完成</template>
      </button>
      <button 
        class="cancel-btn" 
        :disabled="isUploading"
        @click="clearFile"
      >
        取消
      </button>
    </div>
	
    <!-- 上传进度 -->
	<div class="progress-container" v-show="uploadProgress > 0">
	  <div class="progress-bar">
		<div class="progress" :style="{ width: uploadProgress + '%' }"></div>
	  </div>
	  <div class="progress-text">{{ uploadProgress }}%</div>
	</div>

	<!-- 状态消息 -->
	<div 
	  v-if="statusMessage" 
	  class="status-message"
	  :class="statusType"
	>
	  <svg v-if="statusType === 'success'" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="status-icon">
		<polyline points="20 6 9 17 4 12"></polyline>
	  </svg>
	  <svg v-if="statusType === 'error'" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="status-icon">
		<circle cx="12" cy="12" r="10"></circle>
		<line x1="15" y1="9" x2="9" y2="15"></line>
		<line x1="9" y1="9" x2="15" y2="15"></line>
	  </svg>
	  <svg v-if="statusType === 'info'" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="status-icon">
		<circle cx="12" cy="12" r="10"></circle>
		<line x1="12" y1="16" x2="12" y2="12"></line>
		<line x1="12" y1="8" x2="12.01" y2="8"></line>
	  </svg>
	  {{ statusMessage }}
	</div>
  </div>
</template>

<script>
export default {
  name: 'FileUploader',
  data() {
    return {
      selectedFile: null,
      fileName: '',
      fileSize: 0,
      previewSrc: '',
      fileType: '',
      uploadProgress: 0,
      statusMessage: '',
      statusType: '', // success, error, info
      isUploading: false,
      isDragging: false,
      previewLoading: false,
	  uploadTask: null
    };
  },
  methods: {
    chooseFile() {
      // 如果正在上传，不允许选择新文件
      if (this.isUploading) {
        this.showMessage('文件上传中，请等待完成', 'info');
        return;
      }
      
      uni.chooseFile({
        count: 1, // 选择文件数量，默认1
        type: 'all', // 可选all/image/video/audio/file
        success: (res) => {
          this.handleFileSelect(res.tempFiles[0]);
        },
        fail: (err) => {
          console.log('选择文件失败：', err);
          this.showMessage('选择文件失败，请重试', 'error');
        }
      });
    },
    
    handleDrop(e) {
      this.isDragging = false;
      if (this.isUploading) {
        this.showMessage('文件上传中，请等待完成', 'info');
        return;
      }
      
      // 获取拖放的文件
      const files = e.dataTransfer.files;
      if (files && files.length > 0) {
        this.handleFileSelect(files[0]);
      }
    },
    
    handleFileSelect(file) {
      // 清除之前的状态
      this.clearStatus();
      
      // 检查文件大小 (10MB)
      const maxSize = 10 * 1024 * 1024; // 10MB
      if (file.size > maxSize) {
        this.showMessage('文件大小不能超过10MB', 'error');
        return;
      }
      
      this.selectedFile = file;
      this.fileName = file.name;
      this.fileSize = file.size;
      
      // 确定文件类型
      if (file.type.startsWith('image/')) {
        this.fileType = 'image';
        this.previewSrc = file.path || file.tempFilePath || URL.createObjectURL(file);
        this.previewLoading = true;
      } else if (file.type.startsWith('video/')) {
        this.fileType = 'video';
        this.previewSrc = file.path || file.tempFilePath || URL.createObjectURL(file);
        this.previewLoading = true;
      } else {
        this.fileType = 'other';
        this.previewSrc = 'other'; // 非图片视频也显示预览区域
      }
      
      this.showMessage(`已选择文件: ${this.fileName}`, 'info');
    },
    
    previewLoaded() {
      this.previewLoading = false;
    },
    
    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes';
      
      const k = 1024;
      const sizes = ['Bytes', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    },
    
    uploadFile() {
      if (!this.selectedFile) return;
      
      this.isUploading = true;
      this.uploadProgress = 0;
      this.showMessage('开始上传文件...', 'info');
      
      // 处理不同来源的文件路径
      let filePath;
      if (this.selectedFile.path) {
        filePath = this.selectedFile.path;
      } else if (this.selectedFile.tempFilePath) {
        filePath = this.selectedFile.tempFilePath;
      } else if (this.selectedFile instanceof File) {
        // 对于拖拽的原生File对象，需要特殊处理
        // 注意：uni.uploadFile可能需要本地文件路径，这里需要根据实际环境调整
        this.showMessage('暂不支持该类型文件上传', 'error');
        this.isUploading = false;
        return;
      } else {
        this.showMessage('无法获取文件路径', 'error');
        this.isUploading = false;
        return;
      }
      
      // 创建上传任务
      const uploadTask = uni.uploadFile({
        url: 'http://localhost:3000/data/upload', // 与后端路由匹配
        filePath: filePath,
        name: 'file', // 与后端multer配置的fieldname一致
        formData: {
          'user': 'test',
          'fileName': this.selectedFile.name, // 传递原始文件名
          'fileType': this.selectedFile.type // 传递文件类型
        },
        success: (uploadFileRes) => {
          if (uploadFileRes.statusCode === 200) { // 先判断状态码
			try {
			  const result = JSON.parse(uploadFileRes.data);
			  // 正常解析后的逻辑
			  this.isUploading = false;
			  this.uploadProgress = 100;
			  if (result.success) {
			    console.log('上传成功', result.data);
			    this.showMessage('文件上传成功', 'success');
			  } else {
			    this.showMessage('上传失败：' + result.message, 'error');
			  }
			} catch (e) {
			  console.error('解析响应失败', e);
			  this.showMessage('响应格式异常，请检查请求', 'error');
			}
		  } else {
			  console.error('上传请求失败，状态码：', uploadFileRes.statusCode);
			  this.showMessage('文件上传失败，服务端返回错误状态', 'error');
		  }
        },
        fail: (err) => {
          this.isUploading = false;
          console.error('上传失败', err);
          
          // 更详细的错误信息
          let errorMsg = '文件上传失败，请重试';
          if (err.errMsg) {
            errorMsg += `: ${err.errMsg}`;
          } else if (err.message) {
            errorMsg += `: ${err.message}`;
          }
          
          this.showMessage(errorMsg, 'error');
        },
        complete: () => {
          this.isUploading = false;
        }
      });
      
      // 监听上传进度
      uploadTask.onProgressUpdate((res) => {
        this.uploadProgress = res.progress;
      });
      
      // 保存上传任务引用，用于取消上传
      this.uploadTask = uploadTask;
    },
    
	// 添加取消上传方法
	cancelUpload() {
	  if (this.uploadTask) {
	    this.uploadTask.abort();
	    this.uploadTask = null;
	    this.isUploading = false;
	    this.uploadProgress = 0;
	    this.showMessage('已取消上传', 'info');
	  }
	},
	
    clearFile() {
	// 释放 blob URL
	  if (this.previewSrc && this.previewSrc.startsWith('blob:')) {
		URL.revokeObjectURL(this.previewSrc);
	  }
      this.selectedFile = null;
      this.fileName = '';
      this.fileSize = 0;
      this.previewSrc = '';
      this.fileType = '';
      this.uploadProgress = 0;
      this.clearStatus();
    },
    
    clearPreview() {
      this.clearFile();
    },
    
    showMessage(message, type) {
      this.statusMessage = message;
      this.statusType = type;
    },
    
    clearStatus() {
      this.statusMessage = '';
      this.statusType = '';
    },
	
	// 组件销毁时释放
	beforeDestroy() {
	  if (this.previewSrc && this.previewSrc.startsWith('blob:')) {
	    URL.revokeObjectURL(this.previewSrc);
	  }
	}
  }
}
</script>

<style scoped>
.upload-container {
  max-width: 600px;
  margin: 40px auto;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
  font-family: Arial, sans-serif;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.upload-container h2 {
  color: #333;
  text-align: center;
  margin-bottom: 30px;
  font-weight: 600;
}

.file-area {
  border: 2px dashed #007bff;
  border-radius: 8px;
  padding: 40px 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s;
  margin-bottom: 20px;
  position: relative;
  overflow: hidden;
}

.file-area-active {
  background-color: rgba(0, 123, 255, 0.05);
  border-color: #0056b3;
}

.upload-icon {
  color: #007bff;
  margin-bottom: 15px;
  transition: transform 0.3s;
}

.file-area:hover .upload-icon {
  transform: scale(1.1);
}

.upload-text {
  color: #495057;
  margin: 0 0 8px 0;
  font-size: 16px;
}

.file-size-hint {
  color: #6c757d;
  margin: 0;
  font-size: 14px;
}

.preview-container {
  margin: 20px 0;
  border: 1px solid #eee;
  border-radius: 8px;
  overflow: hidden;
  transition: all 0.3s;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #f8f9fa;
  border-bottom: 1px solid #eee;
}

.preview-title {
  margin-left: 20px;
  font-weight: 500;
  color: #495057;
  width: 100%;
}

.remove-preview {
  background: none;
  border: none;
  color: #6c757d;
  cursor: pointer;
  border-radius: 5px;
  transition: all 0.2s;
}

.remove-preview:hover {
  color: #dc3545;
  background-color: rgba(220, 53, 69, 0.1);
}

.preview-image, .preview-video {
  width: 100%;
  max-height: 400px;
  object-fit: contain;
  display: block;
}

.other-file-preview {
  display: flex;
  align-items: center;
  padding: 20px;
  gap: 15px;
}

.file-icon {
  color: #6c757d;
  flex-shrink: 0;
}

.other-file-info {
  flex-grow: 1;
}

.other-file-name {
  font-weight: 500;
  margin-bottom: 5px;
  word-break: break-all;
}

.other-file-size {
  color: #6c757d;
  font-size: 14px;
}

.file-info {
  margin: 15px 0;
  padding: 10px 15px;
  background-color: #f8f9fa;
  border-radius: 4px;
}

.file-name {
  font-weight: 500;
  margin-bottom: 5px;
  word-break: break-all;
}

.file-size {
  color: #6c757d;
  font-size: 14px;
}

.button-group {
  display: flex;
  gap: 10px;
  margin: 20px 0;
}

.upload-btn {
  background-color: #007bff;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  flex-grow: 1;
  font-size: 16px;
  transition: all 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.upload-btn:hover:not(:disabled) {
  background-color: #0056b3;
}

.upload-btn:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
  opacity: 0.7;
}

.cancel-btn {
  background-color: #fff;
  color: #6c757d;
  border: 1px solid #ddd;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.cancel-btn:hover:not(:disabled) {
  background-color: #f8f9fa;
  color: #333;
}

.cancel-btn:disabled {
  cursor: not-allowed;
  opacity: 0.7;
}

.progress-container {
  margin: 15px 0;
}

.progress-bar {
  height: 8px;
  background-color: #e9ecef;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 5px;
}

.progress {
  height: 100%;
  background-color: #28a745;
  transition: width 0.3s ease;
}

.progress-text {
  text-align: right;
  font-size: 14px;
  color: #6c757d;
}

.status-message {
  padding: 10px 15px;
  border-radius: 4px;
  margin: 10px 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.status-icon {
  flex-shrink: 0;
}

.success {
  background-color: rgba(40, 167, 69, 0.1);
  color: #28a745;
  border: 1px solid rgba(40, 167, 69, 0.2);
}

.error {
  background-color: rgba(220, 53, 69, 0.1);
  color: #dc3545;
  border: 1px solid rgba(220, 53, 69, 0.2);
}

.info {
  background-color: rgba(23, 162, 184, 0.1);
  color: #17a2b8;
  border: 1px solid rgba(23, 162, 184, 0.2);
}
</style>
